package edu.snake.implement;

import edu.snake.core.GameEngine;
import edu.snake.core.model.arena.Arena;
import edu.snake.core.model.character.Character;
import edu.snake.core.service.MoveAndCollisionController;
import edu.snake.core.utils.Listeners;
import edu.snake.implement.model.CharacterName;
import edu.snake.implement.model.character.listenerDecorator.CharacterListenerImplFrog;
import edu.snake.implement.model.character.listenerDecorator.CharacterListenerImplSnake;
import edu.snake.implement.service.MoveAndCollisionControllerImpl;
import edu.snake.implement.service.SetToArenaCharacterImpl;

import static edu.snake.implement.ConfigConstant.createAndReturnViewController;
import static edu.snake.implement.ConfigConstant.getInstanceFactory;
import static edu.snake.implement.ConfigConstant.getInstanceThreadPoolService;
import static edu.snake.implement.ConfigConstant.getInstanceView;
import static edu.snake.implement.ConfigConstant.getInstanceViewController;


public class GameEngineImpl implements GameEngine {

    private Arena arena;
    private Character snake;
    private int score;
    private MoveAndCollisionController moveAndCollisionController;


    public GameEngineImpl() {
        getInstanceView().getView(createAndReturnViewController(this));
    }

    @Override
    public void killCharacter(Character character) {
        getInstanceThreadPoolService().removeCharacter(character);
    }

    @Override
    public Character createCharacter(CharacterName characterName) {
        Character character = getInstanceFactory().createNewCharacter(characterName);
        //region todo refactor
        if (characterName == CharacterName.SNAKE_HEAD) {
            character = new CharacterListenerImplSnake(character);
            ((Listeners) character).addActionListener(moveAndCollisionController);
            new SetToArenaCharacterImpl().addCharacterToArena(character, arena);
            getInstanceThreadPoolService().addCharacter(character, ConfigConstant.millisSnake);
        } else if (characterName == CharacterName.FROG) {
            character = new CharacterListenerImplFrog(character);
            ((Listeners) character).addActionListener(moveAndCollisionController);
            new SetToArenaCharacterImpl().addCharacterToArena(character, arena);
            getInstanceThreadPoolService().addCharacter(character, ConfigConstant.millisSnake * ConfigConstant.multiplierDelay);
        }
        //endregion
        return character;
    }

    @Override
    public void startGame() {
        arena = getInstanceFactory().createNewArena();
        moveAndCollisionController = new MoveAndCollisionControllerImpl(this, getInstanceViewController());//todo
        snake = createCharacter(CharacterName.SNAKE_HEAD);
        for (int i = 0; i < ConfigConstant.frogCount; i++) {
            createCharacter(CharacterName.FROG);
        }
        setScore(0);
        getInstanceThreadPoolService().startThreads();


    }


    @Override
    public void stopGame() {
        getInstanceThreadPoolService().stopThreads();
        moveAndCollisionController = null;
        arena = null;
    }

    @Override
    public Arena getArena() {
        return arena;
    }

    @Override
    public Character getSnake() {
        return snake;
    }

    @Override
    public int getScore() {
        return score;
    }

    @Override
    public void setScore(int score) {
        this.score = score;
    }
}
